package com.telrob.antlr.type;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import com.google.gson.Gson;
import com.google.gson.annotations.Expose;

public class XnType {
	@Expose(serialize=false)
	protected StringBuffer code=new StringBuffer();
	protected XnType parent;
	public XnType getParent() {
		return parent;
	}
	public void setParent(XnType parent) {
		this.parent = parent;
	}
	/**
	 * 父类调用处理函数
	 */
	public void process() {}
	/***
	 * 返回汇编代码
	 * @return
	 */
	public String getAsmCode() {
		return code.toString();
	}
	/**
	 * 根据名称获取符号的类型，是全局变量，函数参数，还是局部变量
	 * @param name
	 * @return
	 */
	public SymbolType getSymbol(String name) {
		if(parent!=null) {
			return parent.getSymbol(name);
		}
		return null;
	}
	protected void eachExpression(ExpressionType exp,StringBuffer code) {
		String cal=exp.getCal();
		XnType val1=exp.getVal1();
		XnType val2=exp.getVal2();
		
		if((val1 instanceof ExpressionType) &&(val2 instanceof ExpressionType)) {
			//两个都是表达式时候，需要迭代
			eachExpression((ExpressionType)val1,code);
			code.append("movrr bx,dx\r\n");
			eachExpression((ExpressionType)val2,code);
			code.append("movrr cx,dx\r\n");
			if("+".equals(cal)) {
				code.append("addrr bx,cx\r\n");
			}else if("-".equals(cal)) {
				code.append("subrr bx,cx\r\n");
			}else if("*".equals(cal)) {
				code.append("mulrr bx,cx\r\n");
			}else if("/".equals(cal)) {
				code.append("divrr bx,cx\r\n");
			}
			code.append("movrr dx,bx\r\n");
			
		}else if(val1 instanceof ExpressionType) {
			eachExpression((ExpressionType)val1,code);
			code.append("movrr bx,dx\r\n");
			String v2;
			if(val2 instanceof IdType) {
				v2=((IdType)val2).getName();
				SymbolType type=getSymbol(v2);
				if(type==null) {
					System.err.println("变量 "+v2+"没有被定义");
					System.exit(0);
				}
				if(type.getType()==1) {
					code.append("loadd cx,"+v2+"\r\n");
				}else {
					code.append("loads cx,"+type.getIndex()+"\r\n");
				}
			}else{
				v2=((DigitType)val2).getValue();
				code.append("movrn cx,"+v2+"\r\n");
			}
			if("+".equals(cal)) {
				code.append("addrr bx,cx\r\n");
			}else if("-".equals(cal)) {
				code.append("subrr bx,cx\r\n");
			}else if("*".equals(cal)) {
				code.append("mulrr bx,cx\r\n");
			}else if("/".equals(cal)) {
				code.append("divrr bx,cx\r\n");
			}
			code.append("movrr dx,bx\r\n");
			
		}else if(val2 instanceof ExpressionType) {
			eachExpression((ExpressionType)val2,code);
			code.append("movrr cx,dx\r\n");
			String v1;
			if(val1 instanceof IdType) {
				v1=((IdType)val1).getName();
				SymbolType type=getSymbol(v1);
				if(type==null) {
					System.err.println("变量 "+v1+"没有被定义");
					System.exit(0);
				}
				if(type.getType()==1) {
					code.append("loadd bx,"+v1+"\r\n");
				}else {
					code.append("loads bx,"+type.getIndex()+"\r\n");
				}
			}else{
				v1=((DigitType)val1).getValue();
				code.append("movrn bx,"+v1+"\r\n");
			}
			if("+".equals(cal)) {
				code.append("addrr bx,cx\r\n");
			}else if("-".equals(cal)) {
				code.append("subrr bx,cx\r\n");
			}else if("*".equals(cal)) {
				code.append("mulrr bx,cx\r\n");
			}else if("/".equals(cal)) {
				code.append("divrr bx,cx\r\n");
			}else if("%".equals(cal)) {
				code.append("modrr bx,cx\r\n");
			}
			code.append("movrr dx,bx\r\n");
		}else {
			String v1;
			String v2;
			if(val1 instanceof IdType) {
				v1=((IdType)val1).getName();
				SymbolType type=getSymbol(v1);
				if(type==null) {
					System.err.println("变量 "+v1+"没有被定义");
					System.exit(0);
				}
				if(type.getType()==1) {
					code.append("loadd dx,"+v1+"\r\n");
				}else {
					code.append("loads dx,"+type.getIndex()+"\r\n");
				}
			}else{
				v1=((DigitType)val1).getValue();
				code.append("movrn dx,"+v1+"\r\n");
			}
			
			if(val2 instanceof IdType) {
				v2=((IdType)val2).getName();
				SymbolType type=getSymbol(v2);
				if(type==null) {
					System.err.println("变量 "+v2+"没有被定义");
					System.exit(0);
				}
				if(type.getType()==1) {
					code.append("loadd ex,"+v2+"\r\n");
				}else {
					code.append("loads ex,"+type.getIndex()+"\r\n");
				}
			}else{
				v2=((DigitType)val2).getValue();
				code.append("movrn ex,"+v2+"\r\n");
			}
			if("+".equals(cal)) {
				code.append("addrr dx,ex\r\n");
			}else if("-".equals(cal)) {
				code.append("subrr dx,ex\r\n");
			}else if("*".equals(cal)) {
				code.append("mulrr dx,ex\r\n");
			}else if("/".equals(cal)) {
				code.append("divrr dx,ex\r\n");
			}else if("%".equals(cal)) {
				code.append("modrr dx,ex\r\n");
			}
			
			
		}
		
	}
	
	public void printJson(Object obj) {
		try {
			Gson gson=new Gson();
			ScriptEngine eg=new ScriptEngineManager().getEngineByExtension("js");
			String json=gson.toJson(obj);
			Object objJson=eg.eval("unescape('"+json+"')");
			System.out.println(objJson);
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}
